Session 3 — Data visualisation in R

Applied Methods · MA Public Administration

Maxime Walder

2026-10-02

Today’s session

This session develops the course strand on Data visualisation in R.

The aim is not to memorize all possible plots.

The aim is to learn how to choose an appropriate visualisation depending on:

  • the number of variables
  • the type of variables
  • the message we want to communicate

Session’s plan

  • Recap of Session 2
  • Why do we visualize data?
  • Critics of data visualization
  • When do we use which visualisation?
  • The grammar of graphics
  • One variable
  • Two variables
  • Three or more variables
  • Combining plots

Session 2 recap

Session 2 on data manipulation

We saw how to:

  • Import data (set WD, paths)
  • Inspect data (summary(), glimpse(), head/tail())
  • Create variable with dplyr (%>%, mutate())
  • Operators (|, &, ==, !=, +, -, *, >, <, /, %in%)
  • Functions for conditional logic (case_when(), ifelse())

Session 2 recap

A sytaxe exemple to recode data

data <- data %>% 
  mutate(var2 = var1/10,
         var3 = ifelse(var2<.1, "Rather low", "Rather high"),
         var4 = case_when(var3=="Rather low" | var1.b<.5 ~ "Low var 1 or var 1b",
                          var3=="Rather high" | var1.b>.5 ~ "High var 1 or var 1b",
                          .default="Different magnitude var 1 and var 1b"))

Exercice 0

Why do we visualize data ?

  • Visual communication is more accessible than raw numbers.

  • Help to communicate simple message with a handful of visuals.

  • More easily understandable by wider audience.

Presents a summary of the data

  • Oftentimes, provide a clear summary of the visualisation.

  • Choices are made, and these are not random.

  • Data visualization convey a message

  • Depending on how we present the visualization, convey different message.

  • Subject to manipulation.

Results of the SVP 10 milion initiative.

With a different level of analysis

Change the type of map

And for municipality

What to consider

  • Changing levels of aggregation conveys a different message.

  • Changing the surface plotter changes the message.

  • Other things we should look out for?

Plottng the yes shares

And disagregated

Risk with data visualisation

  • Six representation of the exact same data, different message.

  • Important to be critical on how data is represented.

  • Visualizing data summarizes the data.

  • How to recognize figures that do not read well?

Few key important points

  • Labeling axis

  • Conventional order

    • x axis - left to right
    • y axis - bottom to top
  • Representative axis scales

  • Limit the use of colors and shape (when possible)

Few bad exemples:

Few bad exemples:

Few bad exemples:

Few bad exemples:

See URL1

See URL2

The key question

Before writing code, ask:

What do I want to show?

Then ask:

  • How many variables do I want to describe?
  • Are they categorical or continuous?
  • Do I need to show a distribution, a comparison, a relationship, or a trend?
  • Do I need to add groups or facets?

A decision rule

Situation Typical plot
One categorical variable Bar plot
One continuous variable Histogram, density, boxplot
Continuous × continuous Scatterplot
Categorical × continuous Boxplot, violin, jitter
Categorical × categorical Grouped/stacked bars, tile plot
Time × continuous Line plot

Data for today’s session

We use municipal data on direct democratic votes

Each row is one municipality-ballot combinasion.

glimpse(data_mun)
Rows: 1,099,161
Columns: 20
$ DateNameDE      <chr> "2026-06-14 Änderung des Bundesgesetzes über den zivil…
$ DateNameFR      <chr> "2026-06-14 Modification de la loi fédérale sur le ser…
$ PlaceDE         <chr> "......Aeugst am Albis", "......Aeugst am Albis", "...…
$ PlaceFR         <chr> "......Aeugst am Albis", "......Aeugst am Albis", "...…
$ NumberMun       <chr> "0001", "0001", "0001", "0001", "0001", "0001", "0001"…
$ anr             <chr> "6870", "6860", "6850", "6840", "6830", "6823", "6822"…
$ YesPercent      <dbl> 58.50410, 49.20949, 50.21053, 23.79455, 38.08533, 34.2…
$ YesVote         <dbl> 571, 498, 477, 227, 366, 317, 708, 418, 123, 156, 459,…
$ NoVote          <dbl> 405, 514, 473, 727, 595, 609, 223, 527, 648, 610, 413,…
$ Voters          <dbl> 1381, 1381, 1388, 1388, 1388, 1388, 1388, 1388, 1370, …
$ ReceivedBallots <dbl> 994, 1017, 959, 965, 966, 956, 956, 956, 773, 771, 881…
$ Participation   <dbl> 71.97683, 73.64229, 69.09222, 69.52450, 69.59654, 68.8…
$ ValidBallots    <dbl> 976, 1012, 950, 954, 961, 952, 952, 952, 771, 766, 872…
$ PlaceType       <chr> "Municipality", "Municipality", "Municipality", "Munic…
$ Date            <date> 2026-06-14, 2026-06-14, 2026-03-08, 2026-03-08, 2026-…
$ Year            <dbl> 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2025, …
$ TitleDE         <chr> " Änderung des Bundesgesetzes über den zivilen Ersatzd…
$ TitleFR         <chr> " Modification de la loi fédérale sur le service civil…
$ anr.Swissvotes  <dbl> 687.0, 686.0, 685.0, 684.0, 683.0, 682.3, 682.2, 682.1…
$ GDENR           <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …

Data for today’s session

head(data_mun)

Data for today’s session

  • We also will use the Swissvotes data.

  • Each row is a ballot

  • Each column contains information on the ballot

  • You can access the codebook here

head(data_swissvotes)

Data for today’s session

For some visualisations, we use only one ballot.

data_10milion <- data_mun %>%
  filter(anr=="6860")

head(data_10milion)

Part 1 — The grammar of graphics

The logic of ggplot2

A ggplot object is built step by step.

ggplot(data = data,
       aes(x = variable)) +
  geom_...()

Main components:

  • data
  • aesthetic mappings
  • geometric object
  • scales
  • labels
  • theme

A first plot

ggplot(data = data_10milion,
       aes(x = YesPercent)) +
  geom_histogram()

Make the same plot clearer

ggplot(data = data_10milion,
       aes(x = YesPercent)) +
  geom_histogram(bins = 100) +
  theme_minimal() +
  labs(
    title = "Distribution of municipal support for popular ballots",
    x = "Support for populare ballot in 2025",
    y = "Number of Municipalities"
  )

aes() versus fixed properties

Inside aes(): map a variable to a visual feature.

The aes() stands for aestetics.

aes(fill = region)

Outside aes(): set one fixed visual property.

fill = "grey70"

Mapping a variable

ggplot(data = data_swissvotes[is.na(data_swissvotes$br.pos.char)==F & 
                                is.na(data_swissvotes$institution)==F,],
       aes(x = institution, fill = br.pos.char)) +
  geom_bar() +
  theme_minimal()

Setting a fixed property

  • You can fixe properties of the bars directly in the geom
ggplot(data = data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution)) +
  geom_bar(fill = "grey70", color = "black") +
  theme_minimal()

Specifying data in the geom

  • You can also specify data in the geom directly.

  • This can be useful if you want to plot different data in the same plot or different aestetics in the same plot

ggplot()+ # empty
  geom_bar(data = data_swissvotes[is.na(data_swissvotes$br.pos.char)==F & 
                                is.na(data_swissvotes$institution)==F,],
       aes(x = institution, fill = br.pos.char)) +
  theme_minimal()

Updating your plot

You can assign the plot to an object, then add properties to this object

p <- ggplot(data = data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution)) +
  geom_bar(fill = "grey70", color = "black") +
  theme_minimal()

p+labs(title = "Number of ballot by institution type",
       x = "",
       y="Number of ballots")

Exercice 1

Part 2 - Plot one variable

Plots with one variable

Situation Typical plot Useful geom
One categorical variable Bar plot geom_bar()
One continuous variable Histogram geom_histogram()
One continuous variable Density geom_density()
One continuous variable Boxplot geom_boxplot()

One categorical variable

For one categorical variable, we usually show counts or proportions.

Most common option:

geom_bar()

Bar plot: counts

ggplot(data = data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution)) +
  geom_bar() +
  theme_minimal() +
  labs(
    title = "Number of populare ballot by institution type",
    x = "Institution",
    y = "Number of ballots"
  )

Bar plot: proportions

ggplot(data = data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution, 
           y = after_stat(count/sum(count)),
           group = 1)) +
  geom_bar() +
  scale_y_continuous() +
  theme_minimal() +
  labs(
    title = "Share of populare ballot by institution type",
    x = "Institution",
    y = "Share of ballots"
  )

Flip coordinates

Long category labels are often easier to read horizontally.

ggplot(data = data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution, 
           y = after_stat(prop),
           group = 1)) +
  geom_bar() +
  coord_flip() +
  theme_minimal() +
  labs(
    title = "Share of populare ballot by institution type",
    x = "Institution",
    y = "Share of ballots"
  )

Order categories

data_swissvotes[is.na(data_swissvotes$institution)==F,] %>%
  count(institution) %>%
  ggplot(aes(x = reorder(institution, n), y = n)) +
  geom_col() +
  coord_flip() +
  theme_minimal() +
  labs(
    title = "Number of populare ballot by institution type",
    x = "Institution",
    y = "Number of ballots"
  )

And change other aestetics

data_swissvotes[is.na(data_swissvotes$institution)==F,] %>%
  count(institution) %>%
  ggplot(aes(x = reorder(institution, n), y = n)) +
  geom_col(width=.5,
           color = "black", 
           fill="light gray") +
  coord_flip() +
  theme_minimal() +
  labs(
    title = "Number of populare ballot by institution type",
    x = "Institution",
    y = "Number of ballots"
  )

Exercice 2

One continuous variable

For one continuous variable, we usually show a distribution.

Useful options:

  • histogram
  • density plot
  • boxplot
  • cumulative distribution

Histogram

ggplot(data_10milion,
       aes(x = YesPercent)) +
  geom_histogram(bins = 100) +
  theme_minimal() +
  labs(
    title = "Distribution of municipal support for the 10 million initiative",
    x = "Share of municipale support for the ballot",
    y = "Number of municipalities"
  )

Bin width matters

ggplot(data_10milion,
       aes(x = YesPercent)) +
  geom_histogram(binwidth = .5) +
  theme_minimal() +
  labs(
    title = "Distribution of municipal support for the 10 million initiative",
    x = "Share of municipale support for the ballot",
    y = "Number of municipalities"
  )

Bin width matters

ggplot(data_10milion,
       aes(x = YesPercent)) +
  geom_histogram(binwidth = 20) +
  theme_minimal() +
  labs(
    title = "Distribution of municipal support for the 10 million initiative",
    x = "Share of municipale support for the ballot",
    y = "Number of municipalities"
  )

Density plot

ggplot(data_10milion,
       aes(x = YesPercent)) +
  geom_density() +
  theme_minimal() +
  labs(
    title = "Distribution of municipal support for the 10 million initiative",
    x = "Share of municipale support for the ballot",
    y = "Number of municipalities"
  )

Boxplot

ggplot(data_10milion,
       aes(x = YesPercent)) +
  geom_boxplot() +
  theme_minimal() +
  labs(
    title = "Distribution of municipal support for the 10 million initiative",
    x = "Share of municipale support for the ballot",
    y = NA
  )

Cumulative distribution

ggplot(data_10milion,
       aes(x = YesPercent)) +
  stat_ecdf() +
  theme_minimal() +
  labs(
    title = "Cumulative distribution of municipal support for the 10 million initiative",
    x = "Share of municipale support for the ballot",
    y = "Number of municipalities"
  )

Changing axis scales

You can change the scale of the axis with continuous variables.

When a variable is very skewed, a log scale can help.

ggplot2 has build in scale_x_log10 or scale_y_log10 function that do this for you.

Exercice 3

Part 3 — Two variables

Two variables

When we have two variables, the choice of plot depends on the type of each variable.

Variable 1 Variable 2 Typical plot
Continuous Continuous Scatterplot
Categorical Continuous Boxplot, violin, jitter
Categorical Categorical Bar plot, tile plot
Time Continuous Line plot

Continuous × continuous

We often use a scatterplot.

ggplot(data_10milion, aes(x=YesPercent, y=Participation))+
  geom_point()

Adding a regression line

You can add a linear (or other relation) trend with geom_smooth()

ggplot(data_10milion, aes(x=YesPercent, y=Participation))+
  geom_point()+
  geom_smooth(method = "lm")

Exercice 4

Categorical × continuous

A boxplot compares a continuous variable across groups.

ggplot(data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution,
           y = volkja.proz)) +
  geom_boxplot() +
  theme_minimal() +
  labs(
    title = "Distribution of ballot support by institution",
    x = "Direct democratic institution",
    y = "Populare support"
  )

Violin plot

ggplot(data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution,
           y = volkja.proz)) +
  geom_violin() +
  theme_minimal() +
  labs(
    title = "Distribution of ballot support by institution",
    x = "Direct democratic institution",
    y = "Populare support"
  )

Show raw observations

ggplot(data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution,
           y = volkja.proz)) +
  geom_jitter(width = .15, alpha = .6) +
  theme_minimal() +
  labs(
    title = "Distribution of ballot support by institution",
    subtitle = "Each point represents a municipality",
    x = "Direct democratic institution",
    y = "Populare support"
  )

Combine layers

ggplot(data_swissvotes[is.na(data_swissvotes$institution)==F,],
       aes(x = institution,
           y = volkja.proz)) +
  geom_boxplot(outlier.shape = NA) +
  geom_jitter(width = .15, alpha = .5) +
  theme_minimal() +
  labs(
    title = "Distribution of ballot support by institution",
    x = "Direct democratic institution",
    y = "Populare support"
  )

Exercice 5

Categorical × categorical

Grouped bar plot.

ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,],
       aes(x =institution,
           fill = coalition)) +
  geom_bar(position = "dodge") +
  theme_minimal() +
  labs(
    title = "Distribution of coalition across direct democratic institutions",
    x = "Direct democratic institution",
    y = "Number of ballots",
    fill = "Coalition"
  )

Stacked proportions

ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,],
       aes(x =institution,
           fill = coalition)) +
  geom_bar(position = "fill") +
  scale_y_continuous() +
  theme_minimal() +
  labs(
    title = "Distribution of coalition across direct democratic institutions",
    x = "Direct democratic institution",
    y = "Proportion of of ballots",
    fill = "Coalition"
  )

Tile plot

data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,] %>%
  count(institution, coalition) %>%
  ggplot(aes(x = institution,
             y = coalition,
             fill = n)) +
  geom_tile(color = "white") +
  theme_minimal() +
  labs(
    title = "Distribution of coalition across direct democratic institutions",
    x = "Direct democratic institution",
    y = "Coalition",
    fill = "N"
  )

Exercice 6

Time × continuous

Line plots are useful for trends over time.

data_mun %>%
  group_by(Date, GDENR) %>%
  summarize(part = mean(Participation)) %>%
  filter(GDENR==1) %>% 
  ggplot(aes(x = Date,
             y =part)) +
  geom_line() +
  theme_minimal() +
  labs(
    title = "Participationin popular ballot in Aeugst am Albis over-time.",
    x = "Time",
    y = "Participation"
  )

Several lines

When there are several lines, use group.

data_mun %>%
  group_by(Date, GDENR) %>%
  summarize(part = mean(Participation)) %>%
  filter(GDENR %in% c(1:20)) %>% 
  ggplot(aes(x = Date,
             y =part, 
             group=GDENR)) +
  geom_line(linewidth=.3) +
  theme_minimal() +
  labs(
    title = "Participationin popular ballot in 20 municipalities over-time.",
    x = "Time",
    y = "Participation"
  )

Several lines with colour

data_mun %>%
  group_by(Date, GDENR) %>%
  summarize(part = mean(Participation)) %>%
  filter(GDENR %in% c(1:10)) %>% 
  ggplot(aes(x = Date,
             y =part, 
             color=factor(GDENR))) +
  geom_line() +
  theme_minimal() +
  labs(
    title = "Participationin popular ballot in 10 municipalities over-time.",
    x = "Time",
    y = "Participation",
    fill = "Municipality number"
  )

Exercice 7

More than 2 variables

  • One variable on the X axis, one on the Y axis

  • Other variables can be represented with different aestetics components

    • Colors –> by colloring or filling
    • Shapes –> dotted lines, point’s shape
    • Facets –> tables of plots

Colors

ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,],
       aes(x=institution, y=gov.supp, color = coalition))+
  geom_boxplot()+
  labs(title = "Share of support by institution",
       x="Institution",
       y="National support of the government's position",
       color = "Coalition")

Color

  • You can improve the layout by:
    • Choosing colors yourself
    • Replacing the legen more appropriately

Color

ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,],
       aes(x=institution, y=gov.supp, color = coalition))+
  geom_boxplot()+
  labs(title = "Share of support by institution",
       x="Time",
       y="National support",
       color = "Coalition")+
  scale_color_manual(values=c("red", "blue", "grey", "black"))+
  theme(legend.position = "bottom")

Fill

The fill option works the same way as the color.

Instead of modifying the outline, you change the colors that fills the shape

Fill

ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,],
       aes(x=institution, y=gov.supp, fill = coalition))+
  geom_boxplot()+
  labs(title = "Share of support by institution",
       x="Time",
       y="National support",
       fill = "Coalition")+
  scale_fill_manual(values=c("red", "blue", "grey", "black"))+
  theme(legend.position = "bottom")

Setting colors and fills in R

  • You can set the colors with a default list of colors name as we did until now.

  • The full list of colors is available in R:

colors()
  [1] "white"                "aliceblue"            "antiquewhite"        
  [4] "antiquewhite1"        "antiquewhite2"        "antiquewhite3"       
  [7] "antiquewhite4"        "aquamarine"           "aquamarine1"         
 [10] "aquamarine2"          "aquamarine3"          "aquamarine4"         
 [13] "azure"                "azure1"               "azure2"              
 [16] "azure3"               "azure4"               "beige"               
 [19] "bisque"               "bisque1"              "bisque2"             
 [22] "bisque3"              "bisque4"              "black"               
 [25] "blanchedalmond"       "blue"                 "blue1"               
 [28] "blue2"                "blue3"                "blue4"               
 [31] "blueviolet"           "brown"                "brown1"              
 [34] "brown2"               "brown3"               "brown4"              
 [37] "burlywood"            "burlywood1"           "burlywood2"          
 [40] "burlywood3"           "burlywood4"           "cadetblue"           
 [43] "cadetblue1"           "cadetblue2"           "cadetblue3"          
 [46] "cadetblue4"           "chartreuse"           "chartreuse1"         
 [49] "chartreuse2"          "chartreuse3"          "chartreuse4"         
 [52] "chocolate"            "chocolate1"           "chocolate2"          
 [55] "chocolate3"           "chocolate4"           "coral"               
 [58] "coral1"               "coral2"               "coral3"              
 [61] "coral4"               "cornflowerblue"       "cornsilk"            
 [64] "cornsilk1"            "cornsilk2"            "cornsilk3"           
 [67] "cornsilk4"            "cyan"                 "cyan1"               
 [70] "cyan2"                "cyan3"                "cyan4"               
 [73] "darkblue"             "darkcyan"             "darkgoldenrod"       
 [76] "darkgoldenrod1"       "darkgoldenrod2"       "darkgoldenrod3"      
 [79] "darkgoldenrod4"       "darkgray"             "darkgreen"           
 [82] "darkgrey"             "darkkhaki"            "darkmagenta"         
 [85] "darkolivegreen"       "darkolivegreen1"      "darkolivegreen2"     
 [88] "darkolivegreen3"      "darkolivegreen4"      "darkorange"          
 [91] "darkorange1"          "darkorange2"          "darkorange3"         
 [94] "darkorange4"          "darkorchid"           "darkorchid1"         
 [97] "darkorchid2"          "darkorchid3"          "darkorchid4"         
[100] "darkred"              "darksalmon"           "darkseagreen"        
[103] "darkseagreen1"        "darkseagreen2"        "darkseagreen3"       
[106] "darkseagreen4"        "darkslateblue"        "darkslategray"       
[109] "darkslategray1"       "darkslategray2"       "darkslategray3"      
[112] "darkslategray4"       "darkslategrey"        "darkturquoise"       
[115] "darkviolet"           "deeppink"             "deeppink1"           
[118] "deeppink2"            "deeppink3"            "deeppink4"           
[121] "deepskyblue"          "deepskyblue1"         "deepskyblue2"        
[124] "deepskyblue3"         "deepskyblue4"         "dimgray"             
[127] "dimgrey"              "dodgerblue"           "dodgerblue1"         
[130] "dodgerblue2"          "dodgerblue3"          "dodgerblue4"         
[133] "firebrick"            "firebrick1"           "firebrick2"          
[136] "firebrick3"           "firebrick4"           "floralwhite"         
[139] "forestgreen"          "gainsboro"            "ghostwhite"          
[142] "gold"                 "gold1"                "gold2"               
[145] "gold3"                "gold4"                "goldenrod"           
[148] "goldenrod1"           "goldenrod2"           "goldenrod3"          
[151] "goldenrod4"           "gray"                 "gray0"               
[154] "gray1"                "gray2"                "gray3"               
[157] "gray4"                "gray5"                "gray6"               
[160] "gray7"                "gray8"                "gray9"               
[163] "gray10"               "gray11"               "gray12"              
[166] "gray13"               "gray14"               "gray15"              
[169] "gray16"               "gray17"               "gray18"              
[172] "gray19"               "gray20"               "gray21"              
[175] "gray22"               "gray23"               "gray24"              
[178] "gray25"               "gray26"               "gray27"              
[181] "gray28"               "gray29"               "gray30"              
[184] "gray31"               "gray32"               "gray33"              
[187] "gray34"               "gray35"               "gray36"              
[190] "gray37"               "gray38"               "gray39"              
[193] "gray40"               "gray41"               "gray42"              
[196] "gray43"               "gray44"               "gray45"              
[199] "gray46"               "gray47"               "gray48"              
[202] "gray49"               "gray50"               "gray51"              
[205] "gray52"               "gray53"               "gray54"              
[208] "gray55"               "gray56"               "gray57"              
[211] "gray58"               "gray59"               "gray60"              
[214] "gray61"               "gray62"               "gray63"              
[217] "gray64"               "gray65"               "gray66"              
[220] "gray67"               "gray68"               "gray69"              
[223] "gray70"               "gray71"               "gray72"              
[226] "gray73"               "gray74"               "gray75"              
[229] "gray76"               "gray77"               "gray78"              
[232] "gray79"               "gray80"               "gray81"              
[235] "gray82"               "gray83"               "gray84"              
[238] "gray85"               "gray86"               "gray87"              
[241] "gray88"               "gray89"               "gray90"              
[244] "gray91"               "gray92"               "gray93"              
[247] "gray94"               "gray95"               "gray96"              
[250] "gray97"               "gray98"               "gray99"              
[253] "gray100"              "green"                "green1"              
[256] "green2"               "green3"               "green4"              
[259] "greenyellow"          "grey"                 "grey0"               
[262] "grey1"                "grey2"                "grey3"               
[265] "grey4"                "grey5"                "grey6"               
[268] "grey7"                "grey8"                "grey9"               
[271] "grey10"               "grey11"               "grey12"              
[274] "grey13"               "grey14"               "grey15"              
[277] "grey16"               "grey17"               "grey18"              
[280] "grey19"               "grey20"               "grey21"              
[283] "grey22"               "grey23"               "grey24"              
[286] "grey25"               "grey26"               "grey27"              
[289] "grey28"               "grey29"               "grey30"              
[292] "grey31"               "grey32"               "grey33"              
[295] "grey34"               "grey35"               "grey36"              
[298] "grey37"               "grey38"               "grey39"              
[301] "grey40"               "grey41"               "grey42"              
[304] "grey43"               "grey44"               "grey45"              
[307] "grey46"               "grey47"               "grey48"              
[310] "grey49"               "grey50"               "grey51"              
[313] "grey52"               "grey53"               "grey54"              
[316] "grey55"               "grey56"               "grey57"              
[319] "grey58"               "grey59"               "grey60"              
[322] "grey61"               "grey62"               "grey63"              
[325] "grey64"               "grey65"               "grey66"              
[328] "grey67"               "grey68"               "grey69"              
[331] "grey70"               "grey71"               "grey72"              
[334] "grey73"               "grey74"               "grey75"              
[337] "grey76"               "grey77"               "grey78"              
[340] "grey79"               "grey80"               "grey81"              
[343] "grey82"               "grey83"               "grey84"              
[346] "grey85"               "grey86"               "grey87"              
[349] "grey88"               "grey89"               "grey90"              
[352] "grey91"               "grey92"               "grey93"              
[355] "grey94"               "grey95"               "grey96"              
[358] "grey97"               "grey98"               "grey99"              
[361] "grey100"              "honeydew"             "honeydew1"           
[364] "honeydew2"            "honeydew3"            "honeydew4"           
[367] "hotpink"              "hotpink1"             "hotpink2"            
[370] "hotpink3"             "hotpink4"             "indianred"           
[373] "indianred1"           "indianred2"           "indianred3"          
[376] "indianred4"           "ivory"                "ivory1"              
[379] "ivory2"               "ivory3"               "ivory4"              
[382] "khaki"                "khaki1"               "khaki2"              
[385] "khaki3"               "khaki4"               "lavender"            
[388] "lavenderblush"        "lavenderblush1"       "lavenderblush2"      
[391] "lavenderblush3"       "lavenderblush4"       "lawngreen"           
[394] "lemonchiffon"         "lemonchiffon1"        "lemonchiffon2"       
[397] "lemonchiffon3"        "lemonchiffon4"        "lightblue"           
[400] "lightblue1"           "lightblue2"           "lightblue3"          
[403] "lightblue4"           "lightcoral"           "lightcyan"           
[406] "lightcyan1"           "lightcyan2"           "lightcyan3"          
[409] "lightcyan4"           "lightgoldenrod"       "lightgoldenrod1"     
[412] "lightgoldenrod2"      "lightgoldenrod3"      "lightgoldenrod4"     
[415] "lightgoldenrodyellow" "lightgray"            "lightgreen"          
[418] "lightgrey"            "lightpink"            "lightpink1"          
[421] "lightpink2"           "lightpink3"           "lightpink4"          
[424] "lightsalmon"          "lightsalmon1"         "lightsalmon2"        
[427] "lightsalmon3"         "lightsalmon4"         "lightseagreen"       
[430] "lightskyblue"         "lightskyblue1"        "lightskyblue2"       
[433] "lightskyblue3"        "lightskyblue4"        "lightslateblue"      
[436] "lightslategray"       "lightslategrey"       "lightsteelblue"      
[439] "lightsteelblue1"      "lightsteelblue2"      "lightsteelblue3"     
[442] "lightsteelblue4"      "lightyellow"          "lightyellow1"        
[445] "lightyellow2"         "lightyellow3"         "lightyellow4"        
[448] "limegreen"            "linen"                "magenta"             
[451] "magenta1"             "magenta2"             "magenta3"            
[454] "magenta4"             "maroon"               "maroon1"             
[457] "maroon2"              "maroon3"              "maroon4"             
[460] "mediumaquamarine"     "mediumblue"           "mediumorchid"        
[463] "mediumorchid1"        "mediumorchid2"        "mediumorchid3"       
[466] "mediumorchid4"        "mediumpurple"         "mediumpurple1"       
[469] "mediumpurple2"        "mediumpurple3"        "mediumpurple4"       
[472] "mediumseagreen"       "mediumslateblue"      "mediumspringgreen"   
[475] "mediumturquoise"      "mediumvioletred"      "midnightblue"        
[478] "mintcream"            "mistyrose"            "mistyrose1"          
[481] "mistyrose2"           "mistyrose3"           "mistyrose4"          
[484] "moccasin"             "navajowhite"          "navajowhite1"        
[487] "navajowhite2"         "navajowhite3"         "navajowhite4"        
[490] "navy"                 "navyblue"             "oldlace"             
[493] "olivedrab"            "olivedrab1"           "olivedrab2"          
[496] "olivedrab3"           "olivedrab4"           "orange"              
[499] "orange1"              "orange2"              "orange3"             
[502] "orange4"              "orangered"            "orangered1"          
[505] "orangered2"           "orangered3"           "orangered4"          
[508] "orchid"               "orchid1"              "orchid2"             
[511] "orchid3"              "orchid4"              "palegoldenrod"       
[514] "palegreen"            "palegreen1"           "palegreen2"          
[517] "palegreen3"           "palegreen4"           "paleturquoise"       
[520] "paleturquoise1"       "paleturquoise2"       "paleturquoise3"      
[523] "paleturquoise4"       "palevioletred"        "palevioletred1"      
[526] "palevioletred2"       "palevioletred3"       "palevioletred4"      
[529] "papayawhip"           "peachpuff"            "peachpuff1"          
[532] "peachpuff2"           "peachpuff3"           "peachpuff4"          
[535] "peru"                 "pink"                 "pink1"               
[538] "pink2"                "pink3"                "pink4"               
[541] "plum"                 "plum1"                "plum2"               
[544] "plum3"                "plum4"                "powderblue"          
[547] "purple"               "purple1"              "purple2"             
[550] "purple3"              "purple4"              "red"                 
[553] "red1"                 "red2"                 "red3"                
[556] "red4"                 "rosybrown"            "rosybrown1"          
[559] "rosybrown2"           "rosybrown3"           "rosybrown4"          
[562] "royalblue"            "royalblue1"           "royalblue2"          
[565] "royalblue3"           "royalblue4"           "saddlebrown"         
[568] "salmon"               "salmon1"              "salmon2"             
[571] "salmon3"              "salmon4"              "sandybrown"          
[574] "seagreen"             "seagreen1"            "seagreen2"           
[577] "seagreen3"            "seagreen4"            "seashell"            
[580] "seashell1"            "seashell2"            "seashell3"           
[583] "seashell4"            "sienna"               "sienna1"             
[586] "sienna2"              "sienna3"              "sienna4"             
[589] "skyblue"              "skyblue1"             "skyblue2"            
[592] "skyblue3"             "skyblue4"             "slateblue"           
[595] "slateblue1"           "slateblue2"           "slateblue3"          
[598] "slateblue4"           "slategray"            "slategray1"          
[601] "slategray2"           "slategray3"           "slategray4"          
[604] "slategrey"            "snow"                 "snow1"               
[607] "snow2"                "snow3"                "snow4"               
[610] "springgreen"          "springgreen1"         "springgreen2"        
[613] "springgreen3"         "springgreen4"         "steelblue"           
[616] "steelblue1"           "steelblue2"           "steelblue3"          
[619] "steelblue4"           "tan"                  "tan1"                
[622] "tan2"                 "tan3"                 "tan4"                
[625] "thistle"              "thistle1"             "thistle2"            
[628] "thistle3"             "thistle4"             "tomato"              
[631] "tomato1"              "tomato2"              "tomato3"             
[634] "tomato4"              "turquoise"            "turquoise1"          
[637] "turquoise2"           "turquoise3"           "turquoise4"          
[640] "violet"               "violetred"            "violetred1"          
[643] "violetred2"           "violetred3"           "violetred4"          
[646] "wheat"                "wheat1"               "wheat2"              
[649] "wheat3"               "wheat4"               "whitesmoke"          
[652] "yellow"               "yellow1"              "yellow2"             
[655] "yellow3"              "yellow4"              "yellowgreen"         

Setting colors and fills in R

  • In programmation, colors can also be specified with HEX numerotation

  • For instance: #2E86AB equals to steelblue

  • You can easily find hex color codes in google.

Setting colors and fills in R

  • Finally, you can also use the rgb notation (red, green, blue)

  • In R, the rgb() function enables yu to set the correct amont of each primary color.

rgb(
  red = 46, 
  green = 134, 
  blue = 171,
  maxColorValue = 255
)
[1] "#2E86AB"

Shapes

  • For lines and points, you can also vary the shape.
ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,]
       , aes(x=as.Date(datum, "%d.%m.%Y"),
                            y=gov.supp,
                            shape=coalition))+
  geom_point()

And for lines

data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,] %>% 
  group_by(legislatur, coalition) %>% 
  mutate(gov.supp=mean(gov.supp, na.rm=T)) %>% 
  ggplot()+
  geom_line(aes(x=as.Date(datum, "%d.%m.%Y"),
                y=gov.supp,
                linetype = coalition))

Facets

  • You can facet your plot by a specific variable
ggplot(data_swissvotes[is.na(data_swissvotes$coalition)==F & 
                         is.na(data_swissvotes$institution)==F,],
       aes(x=institution, y=gov.supp))+
  geom_boxplot()+
  facet_wrap(~coalition)+
  labs(title = "Share of support by institution",
       x="Time",
       y="National support")

Combining plots

Sometimes one figure cannot show everything clearly.

We can combine several plots into one layout.

For this, the patchwork or ggarrange packages are very useful.

patchwork package

When you have different plots assigned to different objects, the patchwork package can combine them simply

p1 <- ggplot(...)
p2 <- ggplot(...)
p3 <- ggplot(...)

p1+p2 ### One next to the other

p1/p2 ## Ont on top of the other

(p1+p2)/p3 ## First line has two plots, bottom line has one

patchwork package

p1+p2

ggarrange

ggarrange(p1,p2, nrow=1, ncol=2,
          legend = "bottom", common.legend = T)

Saving plot

  • ggplot2 has a function called ggsave with which yu can save your plot to a file.

  • First you generate the plot, then you can use the ggsave to save it into a fil so that you have:

# Generate the plot 

ggplot(...)+
  geompoint()

ggsave(filename = "plot.png",
       width = ,
       dpi = )

Saving plot

  • Anther way is to use the png()function before the plot.

  • Then you generate the plot and run the dev.off() function.

# Generate the plot 
png("plot.png", width=3000, height=2000, res=300)
ggplot(...)+
  geompoint()
dev.off()

Exercice 8

Discussion

For each figure, ask:

  • What is the main message?
  • What comparison is easy to see?
  • What comparison is difficult to see?
  • Are any design choices misleading?
  • Could the figure be simplified?

Summary

What we learned

  • ggplot2 builds plots step by step.
  • Plot choice depends on the number and type of variables.
  • Layers can combine different visual summaries.
  • Additional variables can be shown with colour, shape, size, groups, or facets.
  • Labels, scales, themes, coordinates, and annotations make plots readable.
  • A good figure is not only correct; it is easy to understand.

Visualisation workflow

# 1. Identify the question

# 2. Identify the variable types

# 3. Choose the appropriate geom

# 4. Build the simplest possible plot

# 5. Add additional variables only if useful

# 6. Improve labels, scales, and theme

# 7. Check whether the figure is easy to interpret

# 8. Save the final figure

Questions ?